﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nim.IO;
using System.Text.RegularExpressions;

namespace Nim.AI
{
    class StateManager
    {
        Dictionary<string,NimState> AIStates,HumanStates,p1Moves, p2Moves;

        //Barry's Baby
        public StateManager()
        {
            AIStates = new Dictionary<string,NimState>();
            HumanStates = new Dictionary<string,NimState>();

            p1Moves = new Dictionary<string,NimState>();
            p2Moves = new Dictionary<string, NimState>();
        }

        //Adds a move to the players dictionary
        public void AddMove(string state, int row, int number, bool player)
        {
            NimState nimState = null;

            HumanStates.TryGetValue(state, out nimState);

            if (nimState == null)
            {
                nimState = new NimState();
                HumanStates.Add(state, nimState);

                if (player) p1Moves.Add(state, nimState);
                else p2Moves.Add(state, nimState);
            }

            NimMove move = new NimMove(row, number);

            nimState.AddMove(move);
        }

        //Initialization logix
        public void Initialize()
        {
            LoadStates();
        }

        //Reads the statebucketfile
        //Parses each row
        //Turns it into the corresponding states
        public void LoadStates()
        {
            string rawStates = FileSystem.ReadFile("statebucket");


            string[] states = rawStates.Split('\n');

            Regex stateFinder = new Regex(@"(\d+):");
            Regex moveFinder = new Regex(@"(\{(\d+),(\d+),(-?\d+),(\d+)\})");

            foreach (string state in states)
            {
                state.Replace(Environment.NewLine, "");
                Match stateMatches = stateFinder.Match(state);
                MatchCollection stateMoves = moveFinder.Matches(state);

                string stateName = stateMatches.Groups[1].Value;

                if (stateName != "")
                {
                    NimState nimState = GetState(stateName);
                    if (nimState == null) nimState = new NimState();

                    foreach (Match match in stateMoves)
                    {
                        int row = int.Parse(match.Groups[2].Value);
                        int number = int.Parse(match.Groups[3].Value);
                        int score = int.Parse(match.Groups[4].Value);
                        int games = int.Parse(match.Groups[5].Value);

                        NimMove move = new NimMove(row, number, score, games);

                        nimState.AddMove(move);
                    }

                    AIStates.Add(stateName, nimState);
                }
            }
        }

        //Returns a state with the given name
        public NimState GetState(string name)
        {
            NimState state = null;

            AIStates.TryGetValue(name, out state);

            return state;
        }

        //Writes all of the states to the file
        public void SaveStates()
        {
            FileSystem.OpenFile("statebucket");
            foreach (KeyValuePair<string, NimState> pair in AIStates)
            {
                string line = "";

                string state = pair.Key;
                List<string> moves = new List<string>();

                foreach (NimMove move in pair.Value.GetMoves())
                {
                    int row = move.Row;
                    int number = move.Number;
                    int score = move.Score;
                    int games = move.Games;
                    moves.Add(String.Format("{{{0},{1},{2},{3}}}", row, number, score, games));
                }

                int commas = moves.Count - 1;

                line += state + ":[";

                foreach (string move in moves)
                {
                    line += move;
                    if (commas > 0) line += ",";
                    --commas;
                }

                line += "]";

                FileSystem.FileWriteLine(line);
            }

            FileSystem.CloseFile();
        }

        //Adds a move to the AI states
        public void AddMoveToStateBucket(string state, NimMove move, bool inWinner)
        {
            NimState nimState = GetState(state);

            int row = move.Row;
            int number = move.Number;
            int score = 0;

            if (inWinner) score += 1;
            else score -= 1;

            if (nimState == null)
            {
                nimState = new NimState();
                AIStates.Add(state, nimState);
            }

            move.Score += score;
            move.Games += 1;

            if (!nimState.MoveExists(move)) nimState.AddMove(move);
            else
            {
                nimState.GetMove(row, number).Score += score;
                nimState.GetMove(row, number).Games += 1;
            }
        }

        public Dictionary<string,NimState> GetAIStates(){ return AIStates;}
        public Dictionary<string, NimState> GetHumanStates() { return HumanStates; }
        public Dictionary<string, NimState> Getp1States() { return p1Moves; }
        public Dictionary<string, NimState> Getp2States() { return p2Moves; }
    }
}
